%{
#include <string>
#include "parser.tab.h"

using namespace std;

int line_num = 1;

void handle_multiline_comment();
%}

%option noyywrap
%option yylineno

DIGIT       [0-9]
LETTER      [a-zA-Z]
ID          [_a-zA-Z][_a-zA-Z0-9]*
INTEGER     -?(0|[1-9][0-9]*)
WHITESPACE  [ \t\r]
NEWLINE     \n

%%

"int"       { return INT; }
"void"      { return VOID; }
"if"        { return IF; }
"else"      { return ELSE; }
"while"     { return WHILE; }
"break"     { return BREAK; }
"continue"  { return CONTINUE; }
"return"    { return RETURN; }

"+"         { return ADD; }
"-"         { return SUB; }
"*"         { return MUL; }
"/"         { return DIV; }
"%"         { return MOD; }
"!"         { return NOT; }
"&&"        { return AND; }
"||"        { return OR; }
"<"         { return LT; }
">"         { return GT; }
"<="        { return LE; }
">="        { return GE; }
"=="        { return EQ; }
"!="        { return NE; }
"="         { return ASSIGN; }

";"         { return SEMICOLON; }
","         { return COMMA; }
"("         { return LPAREN; }
")"         { return RPAREN; }
"{"         { return LBRACE; }
"}"         { return RBRACE; }

{INTEGER}   {
    yylval.num = atoi(yytext);
    return NUMBER;
}

{ID}        {
    yylval.str = new string(yytext);
    return ID;
}

{WHITESPACE}+   { /* 忽略空白字符 */ }

{NEWLINE}   { line_num++; }

"//".*      { /* 忽略单行注释 */ }

"/*"        { handle_multiline_comment(); }

.           { 
    fprintf(stderr, "Error at line %d: unexpected character '%s'\n", 
            yylineno, yytext); 
}

%%

void handle_multiline_comment() {
    int c;
    while ((c = yyinput()) != 0) {
        if (c == '\n') {
            line_num++;
        } else if (c == '*') {
            if ((c = yyinput()) == '/') {
                return;
            } else {
                unput(c);
            }
        }
    }
    fprintf(stderr, "Error: unterminated comment at line %d\n", line_num);
}